package com.boho.ecp.cart.service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.ListUtils;

import cn.boho.framework.context.ActionContext;
import cn.boho.framework.po.DynaBeanMap;
import cn.boho.framework.po.POUtils;

import com.boho.ecp.base.model.Product;
import com.boho.ecp.base.model.UserCookie;
import com.boho.ecp.base.service.CookieService;
import com.boho.ecp.cart.dao.CartDao;
import com.boho.ecp.po.MemberCookiePO;
import com.boho.ecp.product.service.ProductService;
import com.boho.ecp.util.JsonUtils;
import com.google.gson.reflect.TypeToken;

public class CartService {
	
	private final static String PARAM_COOKIE = "PARAM_COOKIE";
	private final static Integer COOKIE_AGE = Integer.MAX_VALUE;
	
	
	/**
	 * 保存单个商品到购物车
	 * @param atx
	 * @param productId
	 * @param qty
	 * @throws Exception
	 */
	public static void saveCart(ActionContext atx, Connection con, Integer productId, Integer qty) throws Exception {
		Integer memberId = atx.getIntegerValue("MEMBER_ID", 0);
		if(memberId == 0){
			List<Product> list = (List<Product>)atx.getValue("COOKIE_PRODUCT");
			List<Product> productList = new ArrayList<Product>();
			boolean exist = false;
			for (Product product : list) {
				if(productId.equals(product.getId())){
					product.setQty(product.getQty() + qty);
					exist = true;
				}
				productList.add(product);
			}
			
			if(!exist){
				Product product = new Product();
				product.setId(productId);
				product.setQty(qty);
				productList.add(product);
			}
			
			saveCookie(atx, memberId, productList, COOKIE_AGE);
			atx.setValue("COOKIE_PRODUCT", productList);
			return;
		}
		
		DynaBeanMap dbm = CartDao.getCartByMemberId(con, memberId);
		Date createDate = new Date();
		if(dbm == null){
			List<Product> list = new ArrayList<Product>();
			Product product = new Product();
			product.setId(productId);
			product.setQty(qty);
			list.add(product);
			String p = JsonUtils.toJSON(list);
			
			MemberCookiePO memberCookiePO = new MemberCookiePO();
			memberCookiePO.setMemberId(memberId);
			memberCookiePO.setProduct(p);
			memberCookiePO.setItems(list.size());
			memberCookiePO.setCreateBy(memberId.toString());
			memberCookiePO.setCreateDate(createDate);
			POUtils.insert(con, memberCookiePO, false);
			
			saveCookie(atx, memberId, list, COOKIE_AGE);
			
		} else {
			List<Product> list = JsonUtils.fromJson((String)dbm.get("PRODUCT"), new TypeToken<List<Product>>(){}.getType());
			List<Product> productList = new ArrayList<Product>();
			boolean exist = false;
			for (Product product : list) {
				if(productId.equals(product.getId())){
					product.setQty(product.getQty() + qty);
					exist = true;
				}
				productList.add(product);
			}
			
			if(!exist){
				Product product = new Product();
				product.setId(productId);
				product.setQty(qty);
				productList.add(product);
			}
			
			String p = JsonUtils.toJSON(productList);
			
			MemberCookiePO conditionMemberCookiePO = new MemberCookiePO();
			MemberCookiePO valueMemberCookiePO = new MemberCookiePO();
			conditionMemberCookiePO.setMemberId(memberId);
			valueMemberCookiePO.setProduct(p);
			valueMemberCookiePO.setItems(productList.size());
			valueMemberCookiePO.setUpdateBy(memberId.toString());
			valueMemberCookiePO.setUpdateDate(createDate);
			POUtils.update(con, conditionMemberCookiePO, valueMemberCookiePO, false);
			
			saveCookie(atx, memberId, productList, COOKIE_AGE);
		}
	}
	
	/**
	 * 保存所有选择的商品到购物车
	 * @param atx
	 * @param list
	 * @throws Exception
	 */
	public static void saveCart(ActionContext atx, Connection con, List<Product> list) throws Exception {
		Integer memberId = atx.getIntegerValue("MEMBER_ID", 0);
		
		List<Product> updateList = new ArrayList<Product>();
		for (Product product : list) {
			if(product.getQty() == 0){
				updateList.add(product);
			}
		}
		list.removeAll(updateList);
		
		String p = JsonUtils.toJSON(list);
		
		if(memberId != 0){
			DynaBeanMap dbm = CartDao.getCartByMemberId(con, memberId);
			if(dbm == null){
				MemberCookiePO memberCookiePO = new MemberCookiePO();
				memberCookiePO.setMemberId(memberId);
				memberCookiePO.setProduct(p);
				memberCookiePO.setItems(list.size());
				memberCookiePO.setCreateBy(memberId.toString());
				memberCookiePO.setCreateDate(new Date());
				POUtils.insert(con, memberCookiePO, false);
			}
			else{
				MemberCookiePO conditionMemberCookiePO = new MemberCookiePO();
				MemberCookiePO valueMemberCookiePO = new MemberCookiePO();
				conditionMemberCookiePO.setMemberId(memberId);
				valueMemberCookiePO.setProduct(p); 
				valueMemberCookiePO.setItems(list.size());
				valueMemberCookiePO.setUpdateBy(memberId.toString());
				valueMemberCookiePO.setUpdateDate(new Date());
				POUtils.update(con, conditionMemberCookiePO, valueMemberCookiePO, false);
			}
		}
		
		saveCookie(atx, memberId, list, COOKIE_AGE);
	}
	
	/**
	 * 将商品信息保存到cookie，并写入客户端
	 * @param atx
	 * @param memberId
	 * @param list
	 * @param cookieAge
	 */
	private static void saveCookie(ActionContext atx, Integer memberId, List<Product> list, Integer cookieAge) throws Exception{
		UserCookie userCookie = new UserCookie();
		userCookie.setUid(memberId);
		userCookie.setProduct(list);
		userCookie.setItems(list.size());
		String cookieJson = JsonUtils.toJSON(userCookie);
		CookieService.saveCookie(atx, "", "/", PARAM_COOKIE, cookieJson, cookieAge);
	}
	
	/**
	 * 清除购物车
	 * @param atx
	 * @throws Exception
	 */
	public static void clearCart(ActionContext atx, Connection con) throws Exception {
		Integer memberId = atx.getIntegerValue("MEMBER_ID", 0);
		
		MemberCookiePO conditionMemberCookiePO = new MemberCookiePO();
		MemberCookiePO valueMemberCookiePO = new MemberCookiePO();
		conditionMemberCookiePO.setMemberId(memberId);
		valueMemberCookiePO.setProduct("[]");
		valueMemberCookiePO.setItems(0);
		valueMemberCookiePO.setUpdateBy(memberId.toString());
		valueMemberCookiePO.setUpdateDate(new Date());
		POUtils.update(con, conditionMemberCookiePO, valueMemberCookiePO, false);
		
		saveCookie(atx, memberId, ListUtils.EMPTY_LIST, COOKIE_AGE);
	}
	
	/**
	 * 查询用户购物车信息
	 * @param atx
	 * @throws Exception
	 */
	public static void queryCart(ActionContext atx, Connection con) throws Exception {
		Integer memberId = atx.getIntegerValue("MEMBER_ID", 0);
		DynaBeanMap dbm = CartDao.getCartByMemberId(con, memberId);
		if(dbm == null || memberId == 0){
			dbm = new DynaBeanMap();
			List<Product> list = (List<Product>)atx.getValue("COOKIE_PRODUCT");
			dbm.put("PRODUCT", JsonUtils.toJSON(list));
		}
		
		List<Product> plist = new ArrayList<Product>();
		List<DynaBeanMap> cartList = new ArrayList<DynaBeanMap>();
		DynaBeanMap cart = new DynaBeanMap();
		cart.put("AMOUNT", "0.00");
		cart.put("PRODUCT_LIST", new Object[]{});
		cart.put("ITEMS", 0);
		plist = JsonUtils.fromJson((String)dbm.get("PRODUCT"), new TypeToken<List<Product>>(){}.getType());
		List<Integer> idList = new ArrayList<Integer>();
		Map<Integer, Integer> map = new HashMap<Integer, Integer>();
		for (Product product : plist) {
			idList.add(product.getId());
			map.put(product.getId(), product.getQty());
		}
		cartList = ProductService.getProductByIds(con, idList);
		cart = fillCartProduct(cartList, map);
		atx.setValue("CART", cart);
		
		saveCookie(atx, memberId, plist, COOKIE_AGE);
		
	}
	
	/**
	 * 根据购物车商品编号查询所选商品填补信息，并计算单品总价和所有商品总价
	 * @param list
	 * @param map
	 * @return
	 * @throws Exception
	 */
	private static DynaBeanMap fillCartProduct(List<DynaBeanMap> list, Map<Integer, Integer> map) throws Exception {
		DynaBeanMap cart = new DynaBeanMap();
		List productList = new ArrayList();
		BigDecimal amount = new BigDecimal(0);
		for (DynaBeanMap dbm : list) {
			Integer productId = (Integer)dbm.get("PRODUCT_ID");
			BigDecimal price = (BigDecimal)dbm.get("MEMBER_PRICE");
			price = price.setScale(2, RoundingMode.HALF_UP);
			BigDecimal marketPrice = (BigDecimal)dbm.get("MARKET_PRICE");
			marketPrice = marketPrice.setScale(2, RoundingMode.HALF_UP);
			
			Integer qty = map.get(productId);
			BigDecimal singlePrice = price.multiply(new BigDecimal(qty));
			singlePrice = singlePrice.setScale(2, RoundingMode.HALF_UP);
			amount = amount.add(singlePrice);
			dbm.put("QTY", qty);
			dbm.put("AMOUNT", singlePrice);
			dbm.put("MEMBER_PRICE",price);
			dbm.put("POINT", singlePrice.multiply(new BigDecimal(com.boho.ecp.constant.Product.POINT_RATE))); // 积分
			dbm.put("MARKET_PRICE", marketPrice);
			productList.add(dbm);
		}
		amount = amount.setScale(2, RoundingMode.HALF_UP);
		cart.put("AMOUNT", amount.toString());
		cart.put("PRODUCT_LIST", productList.toArray());
		cart.put("ITEMS", productList.size());
		return cart;
	}
}
